脚手架命令注册和执行过程开发
本周收获
- 如何设计高性能脚手架
- Node 多进程开发
- JavaScript 面向对象的实战技巧
主要内容
- 图解高性能脚手架架构设计方法
- 封装通用的 Package 和 Command 类
- 基于缓存 + Node 多进程实现动态命令加载和执行
- 将业务逻辑和脚手架框架彻底解耦
- Node 多进程开发——child_process源码分析- 深入Node源码,看清 spawn/exec/execFile/fork的本质区别
 
- 深入Node源码,看清 
脚手架命令注册
使用 commander 库
脚手架优化
为什么要优化
- cli 安装速度慢:所有 package 都集成在 cli 里,因此当命令较多时,会减慢cli的安装速度 - 当前的cil结构  
- 灵活性差: - init命令只能使用- @imooc-cli-dev/init包,对于集团公司而言,每个项目组的- init命令可能都不相同,可能需要实现 init 命令动态化。- 团队A使用 @imooc-cli-dev/init作为初始化模块
- 团队B使用自己开发的 @imooc-cli-dev/my-init作为初始化模块
 
- 团队A使用 
优化结果

脚手架命令动态加载功能架构设计
架构图

node 命令执行源码
node -e "require('./xx/yy/index.js')"
Package 对象功能
- 获取入口文件的路径
- 判断当前package是否存在
- 安装package
- 更新package
获取入口文件的路径 的实现
- 获取 package.json所在目录,使用pkg-dir库
- 读取 package.json
- 找到属性 main,没有的话,找属性lib,拼接为路径
- 路径兼容(macOS/windows)
安装package
使用 cnpm 的 npminstall 包安装。在执行 cnpm install 命令安装npm包时,实际用到的就是 npminstall
实例代码如下。npminstall() 返回一个 promise 对象。
const npminstall = require('npminstall');
const path = require('path');
const userhome = require('user-home')
npminstall({
  root: path.resolve(userhome, '.imooc-cli-dev'), // 模块路径
  storeDir: path.resolve(userhome, '.imooc-cli-dev', 'node_modules'), // 实际存储位置,root + node_modules
  registry: 'https://registry.npm.taobao.org',
  pkgs: [
    { name: 'foo', version: '~1.0.0' },
  ], // 指定安装的包名和版本
});
更新package
- fs-extra- fs的替代品。添加了- fs没有的文件系统方法,并支持- Promise。- mkdir -p递归创建文件夹
 
- 获取最新 - npm模块版本号
- 查询最新版本号对应的路径是否存在 
- 如果不存在,直接安装最新版本